
#ifndef els_vm_bytecode_h
#define els_vm_bytecode_h

#include "els.h"
#include "els_VTypes.h"
#include "els_vm_tree.h"
#include "func.h"



#define FIELDS_PER_FLUSH  40
#define MULT_RET	      255
#define tag(o)		((o)->tag)
#define nvalue(o)	((o)->value.n)
#define svalue(o)	((o)->value.ts->str)
#define tsvalue(o)	((o)->value.ts)
#define avalue(o)	((o)->value.a)
#define fvalue(o)	((o)->value.f)
#define uvalue(o)	((o)->value.u)
#define s_object(i)	(els_unit[i].object)
#define s_tag(i)	(tag(&s_object(i)))
#define s_nvalue(i)	(nvalue(&s_object(i)))
#define s_svalue(i)	(svalue(&s_object(i)))
#define s_avalue(i)	(avalue(&s_object(i)))
#define s_fvalue(i)	(fvalue(&s_object(i)))
#define s_uvalue(i)	(uvalue(&s_object(i)))
#define get_word(code,pc)    {code.m.c1 = *pc++; code.m.c2 = *pc++;}
#define get_float(code,pc)   {code.m.c1 = *pc++; code.m.c2 = *pc++;code.m.c3 = *pc++; code.m.c4 = *pc++;}
#define get_code(code,pc)    {code.m.c1 = *pc++; code.m.c2 = *pc++;code.m.c3 = *pc++; code.m.c4 = *pc++;}


typedef void (*Cfunction) (void);
typedef int  (*Input) (void);
typedef enum { 
    PUSHNULL,
    PUSHNUM0, PUSHNUM1, PUSHNUM2,
    PUSHBYTE,PUSHWORD,PUSHFLOAT,PUSHSTRING,PUSHFC,
    PUSHLET0, PUSHLET1, PUSHLET2, PUSHLET3, PUSHLET4,
    PUSHLET5, PUSHLET6, PUSHLET7, PUSHLET8, PUSHLET9,
    PUSHLET,PUSHGLOBAL,PUSHINDEXED,PUSHSELF,

    STORELET0, STORELET1, STORELET2, STORELET3,STORELET4,
    STORELET5, STORELET6, STORELET7, STORELET8,STORELET9,
    STORELET,STOREGLOBAL,STOREINDEXED0,STOREINDEXED,STORELIST0,STORELIST,STORERECORD,
 
    ADJUST0,ADJUST,CREATEARRAY,EQOP,LTOP,LEOP,GTOP,GEOP,
 
    ADDOP,SUBOP,MULTOP,DIVOP,POWOP,CONCOP,MINUSOP,NOTOP,ONTJMP,ONFJMP,
    
    JMP,UPJMP,IFFJMP,IFFUPJMP,POP,CALLFUNC,RETCODE0,RETCODE,SETLINE
} OpCode;
typedef union{
    Cfunction f;
    double n;
    Type_Tagged_String *ts;
    ELS_FUNC *tf;
    struct Hash *a;
    void *u;
    int	i;
} Value;
typedef struct Object{
    els_Type_System  tag;
    Value value;
} Object;
typedef struct{
    Object  object;
} Symbol;
typedef union{
    struct {char c1; char c2;} m;
    Word w;
} CodeWord;
typedef union{
    struct {char c1; char c2; char c3; char c4;} m;
    float f;
} CodeFloat;
typedef union{
    struct {char c1; char c2; char c3; char c4;} m;
    ELS_FUNC *tf;
} CodeCode;

Object *els_vm_EvmAddress (els_Typesystem_Object o);
char *els_strdup (char *l);
void  els_setinput   (Input fn);	
char *els_lasttext   (void);		
int yylex (void);		        
void els_parse      (ELS_FUNC *tf);	
void els_vm_codedebugline (int line);  
void els_travstack (int (*fn)(Object *));
void els_vm_pushobject (Object *o);
void els_vm_gc_CERROR       (Object *o);

#endif
